package cn.com.dhcc.turbo.dao.registry;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.dao.AbstractCrudDao;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.handler.dbhandler.SingleTransationCircleWithOutResult;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.util.CollectionUtil;
import cn.com.dhcc.app.core.util.JsonUtil;
import cn.com.dhcc.app.core.util.Status;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.pub.core.consts.NodeInfoParam;
import cn.com.dhcc.app.pub.core.consts.TlqConfig;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.entity.registry.Queue;
import cn.com.dhcc.turbo.entity.registry.NodePipeline.PIPE_TYPE;
import cn.com.dhcc.turbo.entity.registry.Queue.QueueType;
import cn.com.dhcc.turbo.service.registry.NodeInfoService;

/**
 * 队列信息Dao
 */
@Repository
public class QueueDao extends AbstractCrudDao<Queue> {
	
	@Autowired
	NodeInfoService nodeInfoService;
	
	/**
	 * 根据队列名称获取队列信息
	 * @param queueName
	 * @return
	 * @throws DaoException
	 */
	public Queue getByQueueName(String queueName) throws DaoException {
		return this.getByUniqueProperty("queue_name", queueName);
	}
	
	/**
	 * 初始化本地队列记录
	 * @param nodeInfo
	 * @return
	 */
	public Status initLocalLqRecord() {
		String msg = "";
		Status status = Status.getInstance();
		try {
			String localNodeId = null;
			NodeInfo localNode = nodeInfoService.getLocalNode();
			if(NodeInfoParam.isMwr() && localNode != null){
				localNodeId = localNode.getId();
			}
			Date now = new Date();
			Map<String, Queue> allQueueMap = new HashMap<String, Queue>();
			List<Queue> lqList = getLocalQueueList();
			List<Queue> addLqList = new ArrayList<Queue>();

			Queue lqCmData = new Queue();
			lqCmData.setId(UUIDGenerator.getUUID());
			lqCmData.setNodeId(localNodeId);
			lqCmData.setQueueType(Queue.QueueType.LQ.value());
			lqCmData.setQueueName(TlqConfig.LQ_CM_DATA);
			lqCmData.setQueueDesc("常规数据接收队列");
			lqCmData.setBrokerType(Queue.BrokerType.TLQ.value());
			lqCmData.setRemark("系统自动创建的本地队列");
			lqCmData.setMtime(now);
			allQueueMap.put(lqCmData.getQueueName(), lqCmData);

			Queue lqCmDataMonitor = new Queue();
			lqCmDataMonitor.setId(UUIDGenerator.getUUID());
			lqCmDataMonitor.setNodeId(localNodeId);
			lqCmDataMonitor.setQueueType(Queue.QueueType.LQ.value());
			lqCmDataMonitor.setQueueName(TlqConfig.LQ_CM_DATA_LOG);
			lqCmDataMonitor.setQueueDesc("常规数据接收监控队列");
			lqCmDataMonitor.setBrokerType(Queue.BrokerType.TLQ.value());
			lqCmDataMonitor.setRemark("系统自动创建的本地队列");
			lqCmDataMonitor.setMtime(now);
			allQueueMap.put(lqCmDataMonitor.getQueueName(), lqCmDataMonitor);

		/*	Queue lqSqlData = new Queue();
			lqSqlData.setId(UUIDGenerator.getUUID());
			lqSqlData.setNodeId(localNodeId);
			lqSqlData.setQueueType(Queue.QueueType.LQ.value());
			lqSqlData.setQueueName(TlqConfig.LQ_SQL_DATA);
			lqSqlData.setQueueDesc("SQL数据接收队列");
			lqSqlData.setBrokerType(Queue.BrokerType.TLQ.value());
			lqSqlData.setRemark("系统自动创建的本地队列");
			lqSqlData.setMtime(now);
			allQueueMap.put(lqSqlData.getQueueName(), lqSqlData);

			Queue lqSqlDataMonitor = new Queue();
			lqSqlDataMonitor.setId(UUIDGenerator.getUUID());
			lqSqlDataMonitor.setNodeId(localNodeId);
			lqSqlDataMonitor.setQueueType(Queue.QueueType.LQ.value());
			lqSqlDataMonitor.setQueueName(TlqConfig.LQ_SQL_DATA_LOG);
			lqSqlDataMonitor.setQueueDesc("常规数据接收监控队列");
			lqSqlDataMonitor.setBrokerType(Queue.BrokerType.TLQ.value());
			lqSqlDataMonitor.setRemark("系统自动创建的本地队列");
			lqSqlDataMonitor.setMtime(now);
			allQueueMap.put(lqSqlDataMonitor.getQueueName(), lqSqlDataMonitor);*/

			Queue lqTest = new Queue();
			lqTest.setId(UUIDGenerator.getUUID());
			lqTest.setNodeId(localNodeId);
			lqTest.setQueueType(Queue.QueueType.LQ.value());
			lqTest.setQueueName(TlqConfig.LQ_TEST);
			lqTest.setQueueDesc("本地测试队列");
			lqTest.setBrokerType(Queue.BrokerType.TLQ.value());
			lqTest.setRemark("系统自动创建的本地队列");
			lqTest.setMtime(now);
			allQueueMap.put(lqTest.getQueueName(), lqTest);

			if (CollectionUtil.hasElement(lqList)) {
				for (Queue lq : lqList) {
					allQueueMap.remove(lq.getQueueName());
				}
			}
			for (Map.Entry<String, Queue> entry : allQueueMap.entrySet()) {
				addLqList.add(entry.getValue());
			}
			if (CollectionUtil.hasElement(addLqList)) {
				this.insertBatch(addLqList);
			}
			msg = "添加本地队列记录成功";
			status.setSuccess(true);
			status.setMsg(msg);
			return status;
		} catch (Exception e) {
			msg = "添加本地队列记录出现异常:" + e.fillInStackTrace();
			status.setSuccess(false);
			status.setMsg(msg);
			return status;
		}
	}
	
	/**
	 * 获取本地队列
	 * @return
	 * @throws DaoException
	 */
	public List<Queue> getLocalQueueList() throws DaoException {
		WhereCondition cnd = new WhereCondition();
		cnd.where().eq("queue_type", Queue.QueueType.LQ.value());
		cnd.orderBy("queue_name");
		return this.list(cnd);
	}

	/**
	 * 获取发送队列
	 * @return
	 * @throws DaoException
	 */
	public List<Queue> getSendQueueList() throws DaoException {
		WhereCondition cnd = new WhereCondition();
		cnd.where().eq("queue_type", Queue.QueueType.SQ.value());
		cnd.orderBy("queue_name");
		return this.list(cnd);
	}

	public void betchInsertOrUpdateSenQueue(final List<Queue> sqList) throws DaoException {
		CM.getDao().doInSingleTransationCircle("批量修改或者插入队列", new SingleTransationCircleWithOutResult() {
			
			@Override
			public void actionInCircle() throws RuntimeException {
				try {
					for (Iterator<Queue> iterator = sqList.iterator(); iterator.hasNext();) {
						Queue queue = iterator.next();
						CM.getDao().saveOrUpdateModuleByIdExecuteNull("修改或者插入队列", queue);
					}
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			}
		});
		
	}
	
	public List<String> getHasExchNodeIds(){
		try {
			NodeInfo localNode = nodeInfoService.getLocalNode();
			String sql=" select " +
					   "     case when t.node_id_creator='"+localNode.getId()+"' " +
					   "     then b.node_code " +
					   "     else  a.node_code " +
					   " end " +
					   " from  " + SI_TABLE("TURBO_EXCH_REL")+"  t " +
					   " inner join "+ SI_TABLE("TURBO_NODE_INFO") + " a on a.id=t.node_id_creator " +
					   " inner join "+ SI_TABLE("TURBO_NODE_INFO") + " b on b.id=t.node_id_to " +
					   " where " +
					   "   t.node_id_creator='"+localNode.getId()+"' " +
					   "   or t.node_id_to='"+localNode.getId()+"' ";
			
			return CM.getDao().listSignleStringColumn("获取有交换关系的节点id", sql,new WhereCondition(),new Object[] {});
		} catch (Exception e) {
			try {
				throw new DaoException("获取有交换关系的节点id发生异常：", e);
			} catch (DaoException e1) {
				e1.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * 获取本节点使用到的tlq的ip地址，用来查询当前节点下tlq的状态
	 * @return {@link List<String>} tlq ip信息
	 */
	@SuppressWarnings("unchecked")
	public List<String> getLocalOtherTlqInfo(){
		List<String> parList = null;
		try {
			final String sql = "SELECT t.paramstr FROM TURBO_NODE_PIPELINE t " +
					"WHERE t.node_id=(SELECT id FROM turbo_node_info WHERE islocal='1' " +
					"AND pipetype='" + PIPE_TYPE.TONGLINKQ.getCode() + "')";
			parList = CM.getDao().listSignleStringColumn("获取本节点部署的其他tlq信息", sql, new WhereCondition(),new Object[] { });
		} catch (DaoException e) {
			e.printStackTrace();
		}
		List<String> ipList = new ArrayList<String>();
		for (String str : parList){
			Map<String, Object> paramMap = JsonUtil.toMap(str);
			if (paramMap.isEmpty()){
				continue;
			}
			//直接获取其Tlq的ip地址
			String ip = (String)paramMap.get("brokerIp");
			ipList.add(ip);
		}
		return ipList;
	}
	
	public int updateDestIp(String src,String dest)throws DaoException{
		String sql="UPDATE  "+SI_TABLE("TURBO_QUEUE")+" SET DEST_IP=? WHERE DEST_IP=? AND QUEUE_TYPE=?";
		try {
			return CM.getDao().update("更新", sql, new Object[] {dest,src,QueueType.SQ.getType()});
		} catch (DaoException e) {
			throw new DaoException(e);
		}
	}
}
